<?php

use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

//use Storage;

/**
 * @param $arr
 * @param int $pid
 * @param int $level
 * @return array
 * 递归分类
 */
function getTree($arr,$pid=0,$level=0)
{
    static $list = [];
    foreach ($arr as $key => $value) {
        if ($value["parent_id"] == $pid) {
            $value["level"] = $level;
            $list[] = $value;
            unset($arr[$key]); //删除已经排好的数据为了减少遍历的次数，当然递归本身就很费神就是了
            getTree($arr,$value["id"],$level+1);
        }
    }
    return $list;
}
/**
 * @param $data
 * @param int $id
 * @return array
 * 引用算法分类
 */
function generateTree($data, $pid=0){

    //初始化儿子
    $child = [];
    //循环所有数据找$id的儿子
    foreach ($data as $key => $datum) {
        //找到儿子了
        if ($datum['parent_id'] == $pid) {
            //保存下来，然后继续找儿子的儿子
            $child[] = $datum;
            //先去掉自己，自己不可能是自己的儿孙
            unset($data[$key]);
            //递归找，并把找到的儿子放到一个child的字段中
            $children = generateTree($data, $datum['id']);
            if(!empty($children)){
                $datum['child'] = $children;
            }
        }
    }
    return $child;

}

/**
 * @return mixed|string
 * 获取IP地址
 */
function getIp(){
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {//ip是否来自共享互联网
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){//ip是否来自代理
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {//ip是否来自远程地址
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    return $ip ? $ip : '127.0.0.1';
}

/**
 * @param $prefix
 * @return string
 * 生成随机数编码
 */
function generateMark($prefix){
    $time = time();
    $date = date('Ymd',$time);
    $rand = mt_rand(10000,99999);
    $mark = $prefix.$date.$rand;
    return $mark;
}

/**
 * @param $mark
 * @return int|string
 * 生成连续编码
 */
function seriesNum($mark = null){
    if(is_null($mark)){
        $number = 0;
    }
    if(is_numeric($mark)){
        $number = $mark+1;
    }
    return $number;
}

/**
 * @return string
 * 生成api_token
 */
function generateToken($length=60) {

    $api_token = Str::random($length);

    return $api_token;
}

/**
 * @return string
 * 生成唯一订单号
 */
function genOrderNumber() {
    return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
}

/**
 * @return string
 * 封装消息
 * 200 数据获取成功
 * 201 数据创建成功
 * 204 数据删除成功
 * 205 数据修改成功
 * 400 参数请求错误
 * 404 找不到
 * 401 权限认证失败
 * 500 服务器内部错误
 */
function encodeMsg($data,$code)
{
    $unknownError = 'unknown error';
    $msg_list = array(
        200=>'success',
        201=>'created',
        204=>'deleted',
        400=>'param error',
        404=>'api not found',
        401=>'auth fail',
        500=>'server error',
        205=>'reset content'
    );
    $res = new stdClass();
    $res->msg= array_key_exists($code,$msg_list)?$msg_list[$code]:$unknownError;
    if($code == 404){
        $code = 100404;
    }
    $res->code = $code;
    $res->data = $data;
    return $res;
}

function encodeMsgJson($data,$code){
    return json_encode(encodeMsg($data,$code));
}


function genValidate(){
    $backtrace = debug_backtrace();
    $cls_name = $backtrace[1]['class'];
    $method_name = $backtrace[1]['function'];
    $method = new \ReflectionMethod($cls_name,$method_name);
    $docment = $method->getDocComment();
    return genValidateHandler($docment);
}

function genValidateHandler($subject){
        $arr = [];
        $tag = '@bodyParam';
        $pattern= "/{$tag}.*/";
        preg_match_all($pattern,$subject,$m);
        foreach ($m[0] as $k=>$v){
            $tmp = (substr($v,strlen($tag)));
            $tmp_arr = (explode(' ',$tmp));
            $tmp_v = replace($tmp_arr[2])."|".replace($tmp_arr[3]);
            $tmp_k = $tmp_arr[1];
            $arr[$tmp_k] = $tmp_v;
        }
        return $arr;
}

function replace($v){
   $replace_arr = [
       "float"=>'numeric',
       'text'=>"string",
       'optional'=>"",
       'datetime'=>'date_format:"Y-m-d\TH:i:s"',
       "timestamp"=>'date_format:"Y-m-d\TH:i:s"',
       //'datetime'=>"date_format:",
       //'timestamp'=>"date_format",
   ];
   if(array_key_exists($v,$replace_arr)){
       return $replace_arr[$v];
   }
   return $v;
}


//生成随机数
function getRandNumber($start=0,$end=9,$length=8)
{
    //初始化变量为0
    $connt = 0;
    //建一个新数组
    $temp = array();
    while ($connt < $length) {
        //在一定范围内随机生成一个数放入数组中
        $temp[] = mt_rand($start, $end);
        //$data = array_unique($temp);
        //去除数组中的重复值用了“翻翻法”，就是用array_flip()把数组的key和value交换两次。这种做法比用 array_unique() 快得多。
        $data = array_flip(array_flip($temp));
        //将数组的数量存入变量count中
        $connt = count($data);
    }
    //为数组赋予新的键名
    shuffle($data);
    //数组转字符串
    $str = implode(",", $data);
    //替换掉逗号
    $number = str_replace(',', '', $str);
    return $number;
}

function pageQuery($query,$request){
    return $query->paginate($request->input('per_page',10));
}
//文件上传地址统一逻辑处理 输入文件暂存地址和文件类型 输出文件最终保存地址
//function upload_img($filePath,$fileType)
//{
//    $fileName = date('Y-m-d').uniqid().'.'.$fileType;
//    $bool = Storage::disk('article')->put($fileName, file_get_contents($filePath)); //存储文件
//    return $fileName;
//}


function loadExport($subject){
    $arr = [];
    $tag = '@queryParam';
    $pattern= "/{$tag}.*/";
    preg_match_all($pattern,$subject,$m);
    foreach ($m[0] as $k=>$v){
        $tmp = (substr($v,strlen($tag)));
        $tmp_arr = (explode(' ',$tmp));
        $arr[$tmp_arr[1]] = $tmp_arr[2];
    }
    return $arr;
}


function genExport(){
    $backtrace = debug_backtrace();
    $cls_name = $backtrace[1]['class'];
    $method_name = $backtrace[1]['function'];
    $method = new \ReflectionMethod($cls_name,$method_name);
    $docment = $method->getDocComment();
    return loadExport($docment);
}

//获取excel表的标题名
function excelTitle(array $commitTitle){
    $arr = [];
    foreach ($commitTitle as $key=>$value){
        $tmp = [];
        $key = explode('|',$key);
        $key2 = explode('->',$key[0]);
        $tmp[$key2[0]] = $value;
        array_push($arr,$tmp);
    }

    return $arr;
}

function excelTitle2(array $commitTitle){
    $arr = [];
    foreach ($commitTitle as $key=>$value){
        array_push($arr,$key);
    }

    return $arr;
}

function excelExport($data,$commitTitle){
    $spreadsheet = new Spreadsheet();
    $sheet = $spreadsheet->getActiveSheet();//这个才是真正的sheet对象 通过这个对象来操控列
    //通过第一个数组获取到title 通过注释信息 把有对应中文注释的字段替换一下
    $title = [];//excel标题
    $exhibitTitle = excelTitle($commitTitle);//获取不带箭头符号的字段 这个用来展示给excel观看和用来数据筛选
    $commitTitle2 = excelTitle2($commitTitle);
    //把exhibitTitle里面的数字去掉 放入title中 title中的类型如 ['id','brand']这样
    foreach ($exhibitTitle as $value){
        foreach ($value as $k1=>$v1){
            array_push($title,$k1);
        }
    }
    $resData = [];
    //data里面的数据太多了 只需要注释中的数据即可 其他的过滤出去
    foreach ($data as $val){
        $tmp = [];
        foreach ($exhibitTitle as $index=>$item){
            foreach ( $item as $k=>$v) {
                try {
                    //使用commitTitle来获取深层嵌套数据
                    $insideData = explode('|',$commitTitle2[$index]);
                    $k_arr = explode("->", $insideData[0]);
                    $tmp_v = $val->{"$k_arr[0]"};
                    //切片数组 如果数组有几个 比如 car->kind->name那么就运行该代码
                    if (sizeof($k_arr) > 1) {
                        foreach (array_slice($k_arr, 1) as $v2) {
                            $tmp_v = $tmp_v->{"$v2"};
                        }
                    }
                    $vx = $tmp_v;
                    if(sizeof($insideData) >1 ){
                        $condition = $insideData[1];//如果有附属的函数
                        $condArr = explode(':',$condition);
                        $func = $condArr[0];//获取要启动的函数 比如bool就是判断是否 status就是输出状态 1=>停止 2=>启动
                        if($func === 'bool'){
                            if($vx){
                                $vx = '是';
                            }else{
                                $vx = '否';
                            }
                        }

                        if($func === 'status'){
                            $conditionStatus = $condArr[1];
                            $conditionArr = explode(',',$conditionStatus);
                            $conditions = array();//最后状态对应的数据会存入这个表
                            foreach ($conditionArr as $item){
                                $items = explode('=>',$item);
                                $conditions[$items[0]] = $items[1];
                            }
                            try{
                                $vx = $conditions[$vx];
                            }catch (Exception $e){
                                $vx = '';
                            }
                        }
                    }
                }catch (\Exception $e){
                    $vx = "";
                }
            }
            array_push($tmp,$vx);
        }
        array_push($resData,$tmp);
    }
    //设置单元格的title
    foreach ($exhibitTitle as $key => $value) {
        // 单元格内容写入
        $cell = '';
        foreach ($value as $v2=>$k2){
            $cell = "{$v2} ({$k2})";
        }
        $sheet->setCellValueByColumnAndRow($key + 1, 1, $cell);
    }
    $row = 2; // 从第二行开始填充数据
    foreach ($resData as $item) {
        $column = 1;
        foreach ($item as $value) {
            // 单元格内容写入
            $sheet->setCellValueByColumnAndRow($column, $row, $value);
            $column++;
        }
        $row++;
    }
    $writer = new Xlsx($spreadsheet);

    return $writer;
}

function excelImport($request){
    $file = $request->file('file');  // 通过laravel的request获取文件
    if ($file && $file->isValid()) {
        // 获取文件相关信息
        $originalName = $file->getClientOriginalName(); // 文件原名
        $ext = $file->getClientOriginalExtension();     // 扩展名
        // $realPath = $file->getRealPath();   //临时文件的绝对路径
        // $type = $file->getClientMimeType();     // image/jpeg
        if ($ext != 'xlsx' && $ext != 'xls') {
            return response()->json(encodeMsg(['message' => '请上传excel文件!'], 400));
        }

        $filename = $originalName;
        // 上传文件 存于服务器
        Storage::disk('public')->makeDirectory('uploads');
        Storage::disk('public')->putFileAs('uploads', $file, $filename);

        //执行同步
        $path = 'public/uploads/' . $filename;
        $data = Excel::toArray('', $path);
        return $data;
    }
}
